#ifndef ___fat32_transaccionC1_informacion_archivo

#define ___fat32_transaccionC1_informacion_archivo 1

#include "f32_mto.c"

#include "f32_st01.c"
#include "f32_st02.c"
#include "f32_st07.c"
#include "f32_st12.c"

#include "f32_opAL.c"

#include <stdint.h>
#include <netinet/in.h>

enum fat32trC1_errores {
  FAT32_C1_ARCHIVO_NO_EXISTE = 1,
  FAT32_C1_ARCHIVO_VACIO = 2
};

struct fat32trC1_datos_entrada {
  char * archivo;
  unsigned int remitente;
};

struct fat32trC1_datos_internos {
  char * nombreArchivo;
  unsigned int remitenteMensaje;
  unsigned int conexion;
  struct fat32_ref_entrada_directorio entrada;
  struct fat32_atributos_archivo atributos;
  unsigned long long descriptor;
  char ** ruta;
  void * datosInternos;
  unsigned long * cadenaClusteres;
  uint32_t cadenaConvertida[20];
  signed short errorDevuelto;
};

void fat32tr_informacion_archivo(char *, unsigned int);
int fat32ctr_informacion_archivo(FAT32_PARAMS_CREACION_TRANSACCION);
int fat32etr_informacion_archivo(FAT32_PARAMS_TRANSACCION);

void fat32tr_informacion_archivo (char * archivo, unsigned int remitente) {
  struct fat32trC1_datos_entrada datos;
  datos.remitente = remitente;
  datos.archivo = malloc(1 + strlen(archivo));
  memcpy(datos.archivo, archivo, 1 + strlen(archivo));
  fat32_crear_transaccion(&fat32ctr_informacion_archivo, &datos, sizeof datos);
}

int fat32ctr_informacion_archivo (FAT32_PARAMS_CREACION_TRANSACCION) {
  struct fat32trC1_datos_entrada * de = datosIniciales;
  struct fat32trC1_datos_internos * di = malloc(sizeof(struct fat32trC1_datos_internos));
  di -> remitenteMensaje = de -> remitente;
  di -> nombreArchivo = de -> archivo;
  *datos = di;
  *handler = &fat32etr_informacion_archivo;
  return 0xE100;
}

int fat32etr_informacion_archivo (FAT32_PARAMS_TRANSACCION) {
  unsigned char estado1;
  int estado2;
  estado2 = estado >> 8;
  estado1 = estado & 255;
  struct fat32trC1_datos_internos * datosT = *datos;
  switch (estado2) {
  case 0x01:
    estado1 = fat32st_obtener_conexion(estado1, numeroTransaccion, &(datosT -> conexion), resultadoOperacion, datosOperacion);
    if (!estado1) estado2 = 0x02;
    break;
  case 0x02:
    estado1 = fat32st_ubicar_entrada_directorio(estado1, numeroTransaccion, datosT -> ruta, &(datosT -> datosInternos), resultadoOperacion,
                                                                                                                            datosOperacion);
    if (!estado1) {
      datosT -> entrada = *((struct fat32_ref_entrada_directorio *) (datosT -> datosInternos));
      free(datosT -> datosInternos);
      estado2 = 0xE1;
      estado1 = 1;
    }
    break;
  case 0x03:
    estado1 = fat32st_obtener_atributos(estado1, numeroTransaccion, (datosT -> entrada).clusterInicial, (datosT -> entrada).posicionEntrada,
                                                                             &(datosT -> datosInternos), resultadoOperacion, datosOperacion);
    if (!estado1) {
      datosT -> atributos = *((struct fat32_atributos_archivo *) (datosT -> datosInternos));
      free(datosT -> datosInternos);
      estado2 = 0xE1;
      estado1 = 2;
    }
    break;
  case 0x04:
    estado1 = fat32tr_liberar_conexion(estado1, numeroTransaccion);
    if (!estado1) {
      estado2 = 0xE1;
      estado1 = 6;
    }
    break;
  case 0xE1:
    switch (estado1) {
    case 0:
      datosT -> ruta = fat32_obtener_ruta(datosT -> nombreArchivo);
      datosT -> descriptor = fat32_generar_descriptor(datosT -> ruta, 0);
      datosT -> cadenaClusteres = NULL;
      datosT -> errorDevuelto = -1;
      estado2 = 0x01;
      break;
    case 1:
      if ((datosT -> entrada).resultado) {
        datosT -> errorDevuelto = FAT32_C1_ARCHIVO_NO_EXISTE;
        estado1 = 5;
      } else {
        estado2 = 0x03;
        estado1 = 0;
      }
      break;
    case 2:
      if (!(datosT -> atributos).clusterInicial) {
        datosT -> errorDevuelto = FAT32_C1_ARCHIVO_VACIO;
        estado1 = 5;
      } else
        estado1 = 3;
      break;
    case 3:
      46;
      unsigned long cluster1 = (datosT -> atributos).clusterInicial;
      fat32_crear_operacion(numeroTransaccion, &fat32op_obtener_cadena_clusteres, &cluster1, sizeof cluster1);
      estado1 = 4;
      break;
    case 4:
      datosT -> cadenaClusteres = datosOperacion;
      fat32_quitar_operacion(numeroTransaccion);
      unsigned char posicion;
      for (posicion = 0; posicion < 20; posicion ++) {
        if (!(datosT -> cadenaClusteres)[posicion]) break;
        (datosT -> cadenaConvertida)[posicion] = (datosT -> cadenaClusteres)[posicion];
        (datosT -> cadenaConvertida)[posicion] = htonl((datosT -> cadenaConvertida)[posicion]);
      }
      if (posicion < 20) for (; posicion < 20; posicion ++) (datosT -> cadenaConvertida)[posicion] = htonl(0);
      estado1 = 5;
      break;
    case 5:
      if ((datosT -> errorDevuelto) != -1)
        mtf_enviar_mensaje(fat32_centro_mensajes, datosT -> remitenteMensaje, MTR_NO_OBTUVO_INFO_ARCH, datosT -> nombreArchivo,
                                                                                               (int) (datosT -> errorDevuelto));
      else
        mtf_enviar_mensaje(fat32_centro_mensajes, datosT -> remitenteMensaje, MTR_INFO_ARCHIVO, datosT -> nombreArchivo,
                                                                                  (void *) (datosT -> cadenaConvertida));
      estado2 = 0x04;
      estado1 = 0;
      break;
    case 6:
      if (datosT -> cadenaClusteres) free(datosT -> cadenaClusteres);
      fat32_destruir_ruta(datosT -> ruta);
      free(datosT -> nombreArchivo);
      free(datosT);
      estado1 = 0;
      estado2 = 0;
    }
    break;
  }
  return (estado2 << 8) | estado1;
}

#endif